//
//  OAuthEngine.m
//  WeiboPad
//
//  Created by junmin liu on 10-10-5.
//  Copyright 2010 Openlab. All rights reserved.
//

#import "OAuthEngine.h"
#import "OAConsumer.h"
#import "OAuthController.h"
#import "ShareKit.h"
#import "OAuth.h"
#import "OAToken.h"
#import "StringUtil.h"
#import "ASIHTTPRequest.h"
#import "ShareError.h"

@interface OAuthEngine()
@property(nonatomic,readonly) OAuth *oAuth;
@end


@implementation OAuthEngine

@synthesize delegate=_delegate;
@synthesize pin = _pin;
@synthesize consumer = _consumer;
@synthesize requestToken = _requestToken;
@synthesize accessToken = _accessToken;
@synthesize shareType=_shareType;
@synthesize baseViewController=_baseViewController;
@synthesize error=_error;

+ (OAuthEngine *)OAuthEngineForType:(NSString*)shareType delegate:(NSObject*)delegate {
    if (shareType==SHARE_QQWEIBO) {
        QQWeiboOAuthEngine *engine =  [[[QQWeiboOAuthEngine alloc] initOAuthWithDelegate: delegate] autorelease];
        engine.shareType = shareType;
        return engine;
    } else {
       OAuthEngine *engine =  [[[OAuthEngine alloc] initOAuthWithDelegate: delegate] autorelease];
        engine.shareType = shareType;
        return engine;
    }
}

- (OAuthEngine *) initOAuthWithDelegate: (NSObject<OAuthEngineDelegate> *) delegate {
    if (self = (id) [super init]) {
		_delegate = delegate;
        _status = kOAuthStatusIdle;
	}
    return self;
}

- (void) dealloc {
    [_pin release];
	[_accessToken release];
	[_requestToken release];
	[_consumer release];
    [_oAuth release];
	[super dealloc];
}

-(OAuth*)oAuth {
    if (!_oAuth) {
        _oAuth = [[OAuth alloc] init];
        _oAuth.consumer = self.consumer;
    }
    return _oAuth;
}

//=============================================================================================================================
#pragma mark OAuth Code
- (void) startAuthorize {
    if (_status!=kOAuthStatusIdle) {
        return;
    }
    _oAuthController =[[OAuthController alloc] init];
    _oAuthController.delegate = self;
    [self.baseViewController presentModalViewController:_oAuthController animated:YES];
    
    [self requestRequestToken];
}

-(void)completeOAuth {
    if (!self.error) {
        [_delegate OAuthEngine:self authrizedWithData:[_accessToken toHttpString]];
    } else {
        [_delegate OAuthEngine:self failedWithError:self.error];
    }
    self.requestToken = nil;
    self.accessToken = nil;
    _status = kOAuthStatusIdle;
}

-(OAToken*)parseResponseToken:(NSString*)data {
    OAToken *token =[[[OAToken alloc] initWithHTTPResponseBody:data] autorelease];
    if (![token isValid]) {
        self.error = [ShareError errorWithCode:kShareErrorLogic erorDesc:data];
    }
    return token;
}

-(void)completeRequest:(ASIHTTPRequest*)request {
    
    if (request&&[request error]) {
        self.error = request.error;
	} 
    
    NSLog(@"error:%@",self.error);
    NSLog(@"response:%@",[request responseString]);
    
    if (self.error) {
        [self completeOAuth];
        return;
    } 
    
    if (_status==kOAuthStatusWaitforRequestToken) {
        self.requestToken = [self parseResponseToken:[request responseString]];
        if (self.error) {
            [self completeOAuth];
        } else {
            [self requestPincode];
        }
    } else if (_status==kOAuthStatusWaitforPin) {
        [self requestAccessToken];
    } else if (_status==kOAuthStatusWaitforAccessToken) {
        self.accessToken = [self parseResponseToken:[request responseString]];
        [self completeOAuth];
    }
}

//A request token is used to eventually generate an access token
- (void) requestRequestToken {
    _status = kOAuthStatusWaitforRequestToken;
    
    NSString *url = [ShareKitUrl requestTokenURL:self.shareType];
    NSString *oauth_header = [self.oAuth oAuthHeaderForMethod:@"POST" andUrl:url andParams:nil andTokenSecret:nil];
    
	// Synchronously perform the HTTP request.
	ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:url]];
	request.requestMethod = @"POST";
    request.delegate = self;
	[request addRequestHeader:@"Authorization" value:oauth_header];
	[request startAsynchronous];
}

- (void) requestPincode {
    NSString *url = [ShareKitUrl authorizeURL:self.shareType];
    NSString *urlWithParam =[url stringByAppendingUrlParameter:@"oauth_token" value:self.requestToken.key];
    NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:urlWithParam]];
    [_oAuthController starWithReqeust:request];
    
    _status = kOAuthStatusWaitforPin;    
}

//this is what we eventually want
- (void) requestAccessToken {    
    _status = kOAuthStatusWaitforAccessToken;   
    
	NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
							_requestToken.key, @"oauth_token",
							_requestToken.pin, @"oauth_verifier",
							nil];
    NSString *url = [ShareKitUrl accessTokenURL:self.shareType];	
	NSString *oauth_header = [self.oAuth oAuthHeaderForMethod:@"POST" andUrl:url andParams:params andTokenSecret:_requestToken.secret];    
	ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:url]];
    request.delegate = self;
	request.requestMethod = @"POST";
	[request addRequestHeader:@"Authorization" value:oauth_header];
	[request startAsynchronous];
}


//=============================================================================================================================
#pragma ASIHTTPRequestDelegate 
- (void)requestFinished:(ASIHTTPRequest *)request {
    [self completeRequest:request];
}

- (void)requestFailed:(ASIHTTPRequest *)request {
    [self completeRequest:request];    
}

//=============================================================================================================================
#pragma OAuthControllerDelegate 
- (void) OAuthControllerFinished: (OAuthController *) controller pinCode:(NSString*)pin {
    self.requestToken.pin = pin;
    [self.baseViewController dismissModalViewControllerAnimated:YES];
    [self performSelector:@selector(completeRequest:) withObject:nil afterDelay:0.1];
}

- (void) OAuthControllerFailed: (OAuthController *) controller error:(NSError*)err {
    [self.baseViewController dismissModalViewControllerAnimated:YES];  
    self.error = err;
    [self performSelector:@selector(completeRequest:) withObject:nil afterDelay:0.1];
}

- (void) OAuthControllerCanceled: (OAuthController *) controller {
    [self.baseViewController dismissModalViewControllerAnimated:YES];  
    self.error = [ShareError errorWithCode:kShareErrorCancel erorDesc:nil];
    [self performSelector:@selector(completeRequest:) withObject:nil afterDelay:0.1];
}

@end


@implementation QQWeiboOAuthEngine

//A request token is used to eventually generate an access token
- (void) requestRequestToken {
    _status = kOAuthStatusWaitforRequestToken;
    
    NSString *url = [ShareKitUrl requestTokenURL:self.shareType];
    NSMutableDictionary *extraParams = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"null",@"oauth_callback",
                                nil];
    NSString *signature = [self.oAuth oAuthSignatureForMethod:@"GET" andUrl:url andParams:extraParams andTokenSecret:nil]; 
    [extraParams addEntriesFromDictionary:self.oAuth.basicOAuthParam];
    url =[url stringByAppendingUrlParameters:extraParams];
    url =[url stringByAppendingUrlParameter:@"oauth_signature" value:signature];
    
	// Synchronously perform the HTTP request.
	ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:url]];
	request.requestMethod = @"GET";
	request.timeOutSeconds = 40;
    request.delegate = self;
	[request startAsynchronous];
}

//this is what we eventually want
- (void) requestAccessToken {
    _status = kOAuthStatusWaitforAccessToken;  
    
	NSMutableDictionary *extraParams = [NSMutableDictionary dictionaryWithObjectsAndKeys:
 							_requestToken.key, @"oauth_token",
							_requestToken.pin, @"oauth_verifier",
							nil];
    NSString *url = [ShareKitUrl accessTokenURL:self.shareType];	
    
    NSString *signature = [self.oAuth oAuthSignatureForMethod:@"GET" andUrl:url andParams:extraParams andTokenSecret:self.requestToken.secret]; 
    
    [extraParams addEntriesFromDictionary:self.oAuth.basicOAuthParam];
    url =[url stringByAppendingUrlParameters:extraParams];
    url =[url stringByAppendingUrlParameter:@"oauth_signature" value:signature];
    
	ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:url]];
	request.requestMethod = @"GET";
    request.delegate = self;
	[request startAsynchronous];
}


@end 
